﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Kokomo.Mirror.Ia32
{
	public class Ia32OpCodeLookup : IaOpCodeLookup
	{
		static Ia32OpCodeLookup()
		{
			Instance = new Ia32OpCodeLookup();
		}

		public static Ia32OpCodeLookup Instance { get; private set; }

		private Ia32OpCodeLookup()
		{
		}

		protected override void DefineSimpleOpCodes(List<OpCode> opCodes)
		{
			base.DefineSimpleOpCodes(opCodes);

			opCodes.AddRange(new OpCode[] {
				// 0x
				new OpCode(0x06, 1, OpCodeForm.Normal, Mnemonic.push, OperandType.ES),
				new OpCode(0x07, 1, OpCodeForm.Normal, Mnemonic.pop, OperandType.ES),
				new OpCode(0x0E, 1, OpCodeForm.Normal, Mnemonic.push, OperandType.CS),
				// 1x
				new OpCode(0x16, 1, OpCodeForm.Normal, Mnemonic.push, OperandType.SS),
				new OpCode(0x17, 1, OpCodeForm.Normal, Mnemonic.pop, OperandType.SS),
				new OpCode(0x1E, 1, OpCodeForm.Normal, Mnemonic.push, OperandType.DS),
				new OpCode(0x1F, 1, OpCodeForm.Normal, Mnemonic.pop, OperandType.DS),
				// 2x
				new OpCode(0x27, 1, OpCodeForm.Normal, Mnemonic.daa),
				new OpCode(0x2F, 1, OpCodeForm.Normal, Mnemonic.das),
				// 3x
				new OpCode(0x37, 1, OpCodeForm.Normal, Mnemonic.aaa),
				new OpCode(0x3F, 1, OpCodeForm.Normal, Mnemonic.aas),
				// 4x
				new OpCode(0x40, 1, OpCodeForm.RegCode, Mnemonic.inc, OperandType.GeneralPurposeRegister | OperandType.OpCodeReg | OperandType.OperandWordOrDword),
				new OpCode(0x48, 1, OpCodeForm.RegCode, Mnemonic.dec, OperandType.GeneralPurposeRegister | OperandType.OpCodeReg | OperandType.OperandWordOrDword),
				// 5x
				new OpCode(0x50, 1, OpCodeForm.RegCode, Mnemonic.push, OperandType.GeneralPurposeRegister | OperandType.OpCodeReg | OperandType.OperandWordOrDword),
				new OpCode(0x58, 1, OpCodeForm.RegCode, Mnemonic.pop, OperandType.GeneralPurposeRegister | OperandType.OpCodeReg | OperandType.OperandWordOrDword),
				// 6x
				new OpCode(0x60, 1, OpCodeForm.Normal, Mnemonic.pushad),
				new OpCode(0x61, 1, OpCodeForm.Normal, Mnemonic.popad),
				new OpCode(0x62, 1, OpCodeForm.Normal, Mnemonic.bound, OperandType.Gv, OperandType.Ma),
				new OpCode(0x63, 1, OpCodeForm.ModRM, Mnemonic.arpl, OperandType.Ew, OperandType.Gw),
				new OpCode(0x68, 1, OpCodeForm.Normal, Mnemonic.push, OperandType.Iz),
				new OpCode(0x6A, 1, OpCodeForm.Normal, Mnemonic.push, OperandType.Ib),
				// 9x
				new OpCode(0x9A, 1, OpCodeForm.Normal, Mnemonic.callf, OperandType.Ap),
				// Cx
				new OpCode(0xC4, 1, OpCodeForm.Normal, Mnemonic.les, OperandType.Gz, OperandType.Mp),
				new OpCode(0xC5, 1, OpCodeForm.Normal, Mnemonic.lds, OperandType.Gz, OperandType.Mp),
				new OpCode(0xCE, 1, OpCodeForm.Normal, Mnemonic.into),
				// Dx
				new OpCode(0xD4, 1, OpCodeForm.Normal, Mnemonic.aam, OperandType.Ib),
				new OpCode(0xD5, 1, OpCodeForm.Normal, Mnemonic.aad, OperandType.Ib),
				// Ex
				new OpCode(0xEA, 1, OpCodeForm.Normal, Mnemonic.jmp, OperandType.Ap),
			});
		}
		protected override void DefineExtendedOpCodeGroups(List<ExtendedOpCodeGroup> groups)
		{
			base.DefineExtendedOpCodeGroups(groups);
			groups.AddRange(new ExtendedOpCodeGroup[] {
			});
		}
	}
}
